/*--
 * RegEdit.cs: Exposes basic registry editing functionality.
 *--
 * For more information, please visit the Metashell Project site:
 *   http://code.google.com/p/metashell/
 *--
 * (c) 2006 Christopher E. Granade.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; exactly version 2
 * of the License applies to this software.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#region Using Statements

	using Microsoft.Win32;

	using System;
	using System.Collections.Generic;
	using System.Xml;
	using Metashell.Core;
	using Metashell.Core.Utility;

#endregion

namespace Metashell.Commands.Basic {

	public class RegEdit : ICommand {
		
		#region Constants
		
			public const string NamespaceURI =
				MetadocNamespaces.RegEdit;
		
		#endregion
		
		#region Private Member Variables
		
			private Metashell.Core.Core core = null;
		
		#endregion
		
		public void RegisterCore(Metashell.Core.Core core_) {
			core = core_;
		}
		
		public string name {
			get { return "regedit"; }
		}
		
		public void Run(
			string parameters,
			Metadoc indoc,
			out Metadoc outdoc
		) {
			
			// Declare variables.
			RegistryKey rk = null;
			XmlElement root = null;
			
			// Set the outdoc to null in case of failure.
			outdoc.data = null;
			outdoc.format = MetadocFormats.Null;
		
			// Break into parts.
			string[] parts = parameters.Split(' ');
			
			// Make sure there is a mode!
			if (parts.Length == 0) {
				core.RaiseError("Please specify a mode. If you want help, please type regedit help.");
				return;
			}
			
			// OK. Now branch based on the mode.
			switch (parts[0]) {
				
				case "lskeys":
					// Check the length.
					if (parts.Length < 2) {
						core.RaiseError("You must specify a registry key when using lskey.");
						return;
					}
					
					// Open the right registry key.
					rk = Registry.CurrentUser.CreateSubKey(parts[1]);
					
					// Get the subkey names.
					string[] subkeys = rk.GetSubKeyNames();
					
					// Start constructing the output.
					outdoc.format = "regkeys";
					outdoc.data = new XmlDocument();
					
					root =
						outdoc.data.CreateElement("rk", "regkeys", NamespaceURI);
						
					outdoc.data.AppendChild(root);
					
					foreach (string sk in subkeys) {
					
						XmlElement xe =
							outdoc.data.CreateElement("rk", "subkey", NamespaceURI);
							
						xe.SetAttribute("name", NamespaceURI, sk);
						
						RegistryKey rsk = rk.CreateSubKey(sk);
						
						xe.SetAttribute("numsubkeys", NamespaceURI,
							rsk.SubKeyCount.ToString());
						xe.SetAttribute("numvalues", NamespaceURI,
							rsk.ValueCount.ToString());
							
						root.AppendChild(xe);
					
					}
					
					return;
				
				case "lsvalues":
					// Check the length.
					if (parts.Length < 2) {
						core.RaiseError("You must specify a registry key when using lskey.");
						return;
					}
					
					// Open the registry key requested.
					rk = Registry.CurrentUser.CreateSubKey(parts[1]);
					
					// Get the values.
					Dictionary<string, object> vals =
						RegistryUtils.GetValuesFromRegistryKey(rk);
						
					// Now, start constructing the output.
					outdoc.format = "regvalues";
					outdoc.data = new XmlDocument();
					
					root =
						outdoc.data.CreateElement("rv", "regvalues", NamespaceURI);
						
					outdoc.data.AppendChild(root);
					
					foreach (KeyValuePair<string, object> val in vals) {
						
						XmlElement xe =
							outdoc.data.CreateElement("rv", "value", NamespaceURI);
							
						xe.SetAttribute("name", NamespaceURI, val.Key);
						
						XmlText xt = outdoc.data.CreateTextNode(val.Value.ToString());
						
						xe.AppendChild(xt);
						
						root.AppendChild(xe);
						
					}
					
					return;
			
				case "set":
					SetVal(parts);
					return;
			
				case "help":
					outdoc.format = MetadocFormats.XHTML;
					outdoc.data = XML.LoadXMLFromFile( 
						core.GetResourcePath("regedit/help.xml"));
						
					return;
					
				case "mkkey":
					MkKey(parts);
					return;
					
				default:
					core.RaiseError("Please use a valid mode.");
					return;
				
			}
			
						
		}
		
		private void SetVal(string[] parts) {
			
			// Check the length.
			if (parts.Length < 4) {
				core.RaiseError("Usage for set: regedit set keyname valuename value.");
				return;
			}
			
			// OK. Now, set the parts to better names.
			string mode = parts[0], keyname = parts[1], valname = parts[2], val = parts[3];
			
			// Let's open the key.
			RegistryKey rk = Registry.CurrentUser.CreateSubKey(keyname);
			rk.SetValue(valname, val);
			
		}
		
		private void MkKey(string[] parts) {
		
			// Check the length.
			if (parts.Length < 2) {
				core.RaiseError("You must specify a registry key when using mkkey.");
				return;
			}
			
			// This command returns null.
			RegistryKey rk = Registry.CurrentUser.CreateSubKey(
				parts[1]);
				
			// We're done. Wasn't that easy?
			return;
			
		}

		
	}

}